package com.fourthGroup.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.fourthGroup.model.Coupon;
import com.fourthGroup.model.UserCoupon;
import com.fourthGroup.mq.CouponProducer;
import com.fourthGroup.service.CouponService;
import com.fourthGroup.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CouponServiceImpl implements CouponService {

    // 使用内存模拟数据库存储（实际项目中应使用数据库）
    private final Map<Long, Coupon> couponMap = new ConcurrentHashMap<>();
    private final Map<Long, List<UserCoupon>> userCouponMap = new ConcurrentHashMap<>();
    private Long couponIdGenerator = 1L;
    private Long userCouponIdGenerator = 1L;

    @Autowired(required = false)
    private CouponProducer couponProducer;

    @Override
    public Result<Coupon> createCoupon(Coupon coupon) {
        coupon.setId(couponIdGenerator++);
        coupon.setCreateTime(new Date());
        coupon.setStock(coupon.getTotal()); // 初始化库存
        couponMap.put(coupon.getId(), coupon);
        log.info("创建优惠券成功: {}", coupon);
        return Result.success(coupon);
    }

    @Override
    public Result<List<Coupon>> listCoupons() {
        List<Coupon> coupons = new ArrayList<>(couponMap.values());
        return Result.success(coupons);
    }

    @Override
    public Result<Coupon> getCoupon(Long id) {
        Coupon coupon = couponMap.get(id);
        if (coupon == null) {
            return Result.error("优惠券不存在");
        }
        return Result.success(coupon);
    }

    @Override
    @SentinelResource(value = "grabCoupon", blockHandler = "grabCouponBlockHandler")
    public Result<Boolean> grabCoupon(Integer userId, Long couponId) {
        // 检查优惠券是否存在
        Coupon coupon = couponMap.get(couponId);
        if (coupon == null) {
            return Result.error("优惠券不存在");
        }

        // 检查优惠券是否过期
        Date now = new Date();
        if (now.after(coupon.getEndTime())) {
            return Result.error("优惠券已过期");
        }

        // 检查用户是否已领取过该优惠券
        if (hasUserGrabbedCoupon(userId, couponId)) {
            return Result.error("您已领取过该优惠券");
        }

        // 秒杀抢购过程中，使用RocketMQ进行请求削峰
        if (couponProducer != null) {
            // 将请求发送到消息队列，异步处理
            couponProducer.sendGrabCouponMessage(userId, couponId);
            return Result.success(true);
        } else {
            // 如果没有配置消息队列，则直接处理
            return processGrabCoupon(userId, couponId);
        }
    }

    /**
     * 处理抢购请求
     */
    public Result<Boolean> processGrabCoupon(Integer userId, Long couponId) {
        // 双重检查
        // 检查优惠券是否存在
        Coupon coupon = couponMap.get(couponId);
        if (coupon == null) {
            return Result.error("优惠券不存在");
        }

        // 检查库存
        synchronized (coupon) {
            if (coupon.getStock() <= 0) {
                return Result.error("优惠券已抢光");
            }

            // 减少库存
            coupon.setStock(coupon.getStock() - 1);

            // 创建用户优惠券
            UserCoupon userCoupon = new UserCoupon();
            userCoupon.setId(userCouponIdGenerator++);
            userCoupon.setUserId(userId);
            userCoupon.setCouponId(couponId);
            userCoupon.setStatus(0); // 未使用
            userCoupon.setGetTime(new Date());

            // 保存用户优惠券
            userCouponMap.computeIfAbsent(Long.valueOf(userId), k -> new ArrayList<>()).add(userCoupon);
            log.info("用户{}成功抢到优惠券{}", userId, couponId);
            return Result.success(true);
        }
    }

    /**
     * Sentinel 降级处理方法
     */
    public Result<Boolean> grabCouponBlockHandler(Integer userId, Long couponId, BlockException e) {
        log.warn("触发限流，用户{}抢券{}被拒绝", userId, couponId);
        return Result.error(429, "系统繁忙，请稍后再试");
    }

    @Override
    public Result<Boolean> useCoupon(Integer userId, Long couponId, String orderId) {
        // 查询用户优惠券
        List<UserCoupon> userCoupons = userCouponMap.getOrDefault(Long.valueOf(userId), new ArrayList<>())
                .stream()
                .filter(uc -> uc.getCouponId().equals(couponId) && uc.getStatus() == 0)
                .collect(Collectors.toList());

        if (userCoupons.isEmpty()) {
            return Result.error("未找到可用的优惠券");
        }

        // 使用优惠券
        UserCoupon userCoupon = userCoupons.get(0);
        userCoupon.setStatus(1); // 已使用
        userCoupon.setUseTime(new Date());
        userCoupon.setOrderId(orderId);
        log.info("用户{}使用优惠券{}，订单号：{}", userId, couponId, orderId);
        return Result.success(true);
    }

    @Override
    public Result<List<UserCoupon>> getUserCoupons(Integer userId) {
        List<UserCoupon> userCoupons = userCouponMap.getOrDefault(Long.valueOf(userId), new ArrayList<>());
        return Result.success(userCoupons);
    }

    @Override
    public void preHeatCouponStock(Long couponId) {
        // 预热库存，实际项目中可能需要将库存提前加载到Redis等缓存中
        Coupon coupon = couponMap.get(couponId);
        if (coupon != null) {
            log.info("预热优惠券{}库存，当前库存: {}", couponId, coupon.getStock());
        }
    }

    /**
     * 检查用户是否已领取过该优惠券
     */
    private boolean hasUserGrabbedCoupon(Integer userId, Long couponId) {
        return userCouponMap.getOrDefault(Long.valueOf(userId), new ArrayList<>())
                .stream()
                .anyMatch(uc -> uc.getCouponId().equals(couponId));
    }
} 